package it.controllocredito.backend.phone;

import it.controllocredito.backend.persistence.CalllogPersistenceManager;
import it.controllocredito.backend.persistence.SogliaPersistenceManager;
import it.controllocredito.backend.persistence.bean.Soglia;
import it.controllocredito.backend.phone.callNotification.CallRunner;
import it.controllocredito.backend.phone.calllog.AsyncRegistroUpdate;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.Toast;

/**
 * TODO: trovare il modo di capire quando la telefonata � ricevuta o effettuata
 * 
 * @author Event
 * 
 */
public class CustomPhoneStateListener extends PhoneStateListener
{

	private static final String	log_class_name	= "CustomPhoneStateListener";

	private int					prevState;

	private String				stateString;

	private Context				context;

	private CallRunner 			callRunner;

	private Thread       		thread;  

	public CustomPhoneStateListener(Context context)
	{
		super();
		Log.d(log_class_name, "- CustomPhoneStateListener created");
		this.prevState = -1;
		this.stateString = "Primo avvio";
		this.context = context;
	}

	@Override
	public void onCallStateChanged(int state, String incomingNumber)
	{

		switch (state)
		{
		case TelephonyManager.CALL_STATE_IDLE:
			this.callHandler(TelephonyManager.CALL_STATE_IDLE,
					new Date().getTime(), incomingNumber);
			break;
		case TelephonyManager.CALL_STATE_RINGING:
			this.callHandler(TelephonyManager.CALL_STATE_RINGING,
					new Date().getTime(), incomingNumber);
			break;
		case TelephonyManager.CALL_STATE_OFFHOOK:
			this.callHandler(TelephonyManager.CALL_STATE_OFFHOOK,
					new Date().getTime(), incomingNumber);
			break;
		}
	}

	private void callHandler(int state, long time, String incomingNumber)
	{
		Log.d(log_class_name, this.getStateString(prevState) + " -> " + this.getStateString(state));

		boolean needToLog = false;

		SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);

		if(sharedPrefs.getBoolean("setting_notify", false))
		{
			// Istanziare thread
			if (callRunner == null)
			{
				callRunner = new CallRunner(context, true);
			}
			if (thread == null)
			{
				thread = new Thread(callRunner); 
			}
		}

		// TODO: Bug dovrebbe entrare qui invece non entra.
		if (state == TelephonyManager.CALL_STATE_OFFHOOK && (prevState == TelephonyManager.CALL_STATE_RINGING))
		{
			if(sharedPrefs.getBoolean("setting_notify", false))
			{
				if (thread != null)
				{
					CalllogPersistenceManager calllogPersistenceManager = new CalllogPersistenceManager(context);
					long secondi_ChiamateEff = calllogPersistenceManager.getTotalTimeOutgoingRegistroChiamate();

					Soglia soglia = null;
					SogliaPersistenceManager spm = new SogliaPersistenceManager(context);
					List<Soglia> sogliaTelList = spm.getRecordsSogliaTel();
					soglia = sogliaTelList.get(0);				

					long millisecondi_minutiRimasti = TimeUnit.MINUTES.toMillis(soglia.getValore()) -  	TimeUnit.SECONDS.toMillis(secondi_ChiamateEff);

					callRunner.setMinutiRimasti(millisecondi_minutiRimasti);
					thread.start();
				//	try {
						//thread.sleep(5);
				//	} catch (InterruptedException e) 
				//	{
				//		e.printStackTrace();
				//	}
				}
			}
		}
		
		// TODO Dovrebe entrare sopra e non qui
		//inizio chiamata in uscita: INIT->HOOK o IDLE->HOOK  
		if ((state == TelephonyManager.CALL_STATE_OFFHOOK) && ((prevState == TelephonyManager.CALL_STATE_IDLE) || (prevState == -1)))
		{
			needToLog = true;
			stateString = "Inizio telefonata in uscita (" + incomingNumber + ") [HOOK]";

			if(sharedPrefs.getBoolean("setting_notify", false))
			{
				if (thread != null)
				{
					CalllogPersistenceManager calllogPersistenceManager = new CalllogPersistenceManager(context);
					long secondi_ChiamateEff = calllogPersistenceManager.getTotalTimeOutgoingRegistroChiamate();

					Soglia soglia = null;
					SogliaPersistenceManager spm = new SogliaPersistenceManager(context);
					List<Soglia> sogliaTelList = spm.getRecordsSogliaTel();
					soglia = sogliaTelList.get(0);				

					long millisecondi_minutiRimasti = TimeUnit.MINUTES.toMillis(soglia.getValore()) -  	TimeUnit.SECONDS.toMillis(secondi_ChiamateEff);

					callRunner.setMinutiRimasti(millisecondi_minutiRimasti);
					thread.start();
				//	try {
						//thread.sleep(5);
				//	} catch (InterruptedException e) 
				//	{
				//		e.printStackTrace();
				//	}
				}
			}
			
		}

		//inizio chiamata in ingresso RING->HOOK o IDLE->HOOK
		if ((state == TelephonyManager.CALL_STATE_RINGING) && ((prevState == TelephonyManager.CALL_STATE_IDLE) || (prevState == -1)))
		{
			needToLog = true;
			stateString = "Inizio telefonata in ingresso (" + incomingNumber + ") [RING]";

		}

		//chiamata in corso: RING->HOOK
		if ((prevState == TelephonyManager.CALL_STATE_RINGING) && (state == TelephonyManager.CALL_STATE_OFFHOOK))
		{
			needToLog = true;
			stateString = "Telefonata in corso... [HOOK]";					

		}
		
		//fine chiamata standard: HOOK->IDLE
		//fine chiamata persa o annullata: RING->IDLE
		if (((prevState == TelephonyManager.CALL_STATE_OFFHOOK) && (state == TelephonyManager.CALL_STATE_IDLE)) || ((prevState == TelephonyManager.CALL_STATE_RINGING) && (state == TelephonyManager.CALL_STATE_IDLE)))
		{
			if(sharedPrefs.getBoolean("setting_notify", false))
			{
				if (thread != null)
				{
					callRunner.setStatoChiamataAttivo(false);

					long minutes = TimeUnit.MILLISECONDS.toMinutes(callRunner.getEstimatedTime());
					long seconds = TimeUnit.MILLISECONDS.toSeconds(callRunner.getEstimatedTime());

					String ultimaChiamata = "";
					long hours = TimeUnit.MILLISECONDS.toHours(callRunner.getEstimatedTime())
							- TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(callRunner.getEstimatedTime()));
					minutes = TimeUnit.MILLISECONDS.toMinutes(callRunner.getEstimatedTime())
							- TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(callRunner.getEstimatedTime()));
					seconds = TimeUnit.MILLISECONDS.toSeconds(callRunner.getEstimatedTime())
							- TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(callRunner.getEstimatedTime()));
					ultimaChiamata = String.format("%02d:%02d:%02d", hours, minutes, seconds);

					Toast.makeText(context,
							"Totale ultima chiamata : " + ultimaChiamata ,
							Toast.LENGTH_LONG).show();

					String minutiRimastiNotifica = "";
					hours = TimeUnit.MILLISECONDS.toHours(callRunner.getMinutiRimastiEffettivi())
							- TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(callRunner.getMinutiRimastiEffettivi()));
					minutes = TimeUnit.MILLISECONDS.toMinutes(callRunner.getMinutiRimastiEffettivi())
							- TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(callRunner.getMinutiRimastiEffettivi()));
					seconds = TimeUnit.MILLISECONDS.toSeconds(callRunner.getMinutiRimastiEffettivi())
							- TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(callRunner.getMinutiRimastiEffettivi()));
					minutiRimastiNotifica = String.format("%02d:%02d:%02d", hours, minutes, seconds);

					Toast.makeText(context,
							"Totale minuti effettivi rimasti : " + minutiRimastiNotifica ,
							Toast.LENGTH_LONG).show();


					// thread.destroy();
					thread = null;
					callRunner = null;
				}
			}

			needToLog = true;
			stateString = "Fine telefonata [RING]";

			Log.i(log_class_name, "Invoking Async Task");
			//			try {
			//				Thread.sleep(20000);
			//			} catch (InterruptedException e) {
			//				e.printStackTrace();
			//			}
			//			Log.i(log_class_name, "Waking up");

			AsyncRegistroUpdate async = new AsyncRegistroUpdate(this.context);
			async.execute("...");

			Log.i(log_class_name, "Going on");

		}

		if ((prevState == TelephonyManager.CALL_STATE_IDLE) && (state == TelephonyManager.CALL_STATE_IDLE))
		{
			needToLog = false;
		}

		if ((prevState == TelephonyManager.CALL_STATE_OFFHOOK) && (state == TelephonyManager.CALL_STATE_OFFHOOK))
		{
			needToLog = false;
		}

		if (needToLog)
		{
			Log.i(log_class_name, stateString);
			prevState = state;
		}

	}

	private String getStateString(int state)
	{
		String stateString = "";

		switch (state)
		{
		case -1:
			stateString = "INIT";
			break;
		case TelephonyManager.CALL_STATE_IDLE:
			stateString = "IDLE";
			break;
		case TelephonyManager.CALL_STATE_RINGING:
			stateString = "RING";
			break;
		case TelephonyManager.CALL_STATE_OFFHOOK:
			stateString = "HOOK";
			break;
		}

		return stateString;
	}
}